package io.gitee.caoxiaoyu97.service.split.agent;

import io.gitee.caoxiaoyu97.service.split.api.ServiceSplit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/*********************************************************
 * 文件名称：ServiceSplitBeanDefinitionScanner.java
 * 系统名称：cxycloud
 * 模块名称：io.gitee.caoxiaoyu97.service.split
 * 功能说明：扫描需要做服务转换的接口
 * 开发人员 @author：caoxy
 * 开发时间 @date：2023/8/4 14:04
 * 修改记录：程序版本  修改日期  修改人员  修改单号  修改说明
 *********************************************************/
@Slf4j
public class ServiceSplitBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
    private static final Map<String, Class<?>> bizInterfaceMap = new ConcurrentHashMap();
    private String interceptorName;

    public ServiceSplitBeanDefinitionScanner(BeanDefinitionRegistry registry, String interceptorName) {
        super(registry);
        this.interceptorName = interceptorName;
    }
    public void registerFilters() {
        this.addIncludeFilter((metadataReader, metadataReaderFactory) -> {
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            try {
                Class<?> aClass = Class.forName(classMetadata.getClassName());
                Method[] methods = aClass.getMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(ServiceSplit.class)){
                        return true;
                    }
                }
            } catch (ClassNotFoundException e) {
            }
            return false;
        });
        // this.addIncludeFilter(new AnnotationTypeFilter(ServiceSplit.class));
        this.addExcludeFilter((metadataReader, metadataReaderFactory) -> {
            String className = metadataReader.getClassMetadata().getClassName();
            return className.endsWith("package-info");
        });
    }
    /**
     * 扫描类路径以查找候选组件。
     * @param basePackage 用于检查带注释类的包
     * @return  一组相应的自动检测bean定义
     */
    @Override
    public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        Set<BeanDefinition> beanDefinitionSet = super.findCandidateComponents(basePackage);
        Set<String> interfaceNames = new HashSet(beanDefinitionSet.size());
        for (BeanDefinition beanDefinition : beanDefinitionSet) {
            String className = beanDefinition.getBeanClassName();
            beanDefinition.setBeanClassName(ProxyFactoryBean.class.getName());
            beanDefinition.setPrimary(true);
            beanDefinition.getPropertyValues().add("proxyInterfaces", className);
            beanDefinition.getPropertyValues().add("interceptorNames", this.interceptorName);
            interfaceNames.add(className);
        }
        initBizInterfaceMap(interfaceNames);
        return beanDefinitionSet;
    }
    private static synchronized void initBizInterfaceMap(Set<String> interfaceNames) {
        for (String interfaceName : interfaceNames) {
            Class<?> interfaceClass = null;

            try {
                interfaceClass = Class.forName(interfaceName);
            } catch (ClassNotFoundException var5) {
                log.warn("not found class [{}]", interfaceName);
            }

            if (interfaceClass != null) {
                bizInterfaceMap.put(interfaceName, interfaceClass);
            }
        }
    }

    public static Map<String, Class<?>> getBizInterfaceMap() {
        return bizInterfaceMap;
    }

    /**
     * 确定给定的bean定义是否符合候选条件。 默认实现检查类是否不是接口并且是否依赖于封闭类。 可以在子类中重写。
     * @param beanDefinition 要检查的bean定义
     * @return bean定义是否符合候选组件的条件
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        AnnotationMetadata metadata = beanDefinition.getMetadata();
        return metadata.isInterface() && metadata.isInterface();
    }

    /**
     * 检查给定候选者的bean名称，确定相应的bean定义是否需要注册或与现有定义冲突。
     * @param beanName bean的建议名称
     * @param beanDefinition 对应的bean定义
     * @return  如果bean可以按原样注册，则为true；false，如果应该跳过它，因为指定名称已有兼容的bean定义
     * @throws IllegalStateException    如果为指定名称找到了现有的、不兼容的bean定义
     */
    @Override
    protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
        if (super.checkCandidate(beanName, beanDefinition)) {
            return true;
        } else {
            log.warn("Skipping ServiceFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' serviceInterface. Bean already defined with the same name!");
            return false;
        }
    }
}
